package com.example.demo.service.impl;

import com.example.demo.exception.UnknownException;
import com.example.demo.pojo.request.CronTriggerCreateRequest;
import com.example.demo.pojo.response.QuartzCronTriggerResponse;
import com.example.demo.pojo.response.QuartzJobDetailResponse;
import com.example.demo.service.QuartzSchedulerService;
import lombok.RequiredArgsConstructor;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Quartz 服务层实现类
 *
 * @author Ethan Blake
 * @version 1.0
 * @since 2024/8/27
 */
@Service
@RequiredArgsConstructor
public class QuartzSchedulerServiceImpl implements QuartzSchedulerService {

    private final Scheduler scheduler;

    /**
     * 获取所有的 JobDetail 信息
     *
     * @return JobDetail 信息列表
     */
    @Override
    public List<QuartzJobDetailResponse> getAllJobDetails() {
        try {
            List<QuartzJobDetailResponse> jobDetailList = new ArrayList<>();
            Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.anyGroup());
            for (JobKey jobKey : jobKeys) {
                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                QuartzJobDetailResponse quartzJobDetail = new QuartzJobDetailResponse();
                quartzJobDetail.setName(jobDetail.getKey().getName());
                quartzJobDetail.setGroup(jobDetail.getKey().getGroup());
                quartzJobDetail.setDescription(jobDetail.getDescription());
                jobDetailList.add(quartzJobDetail);
            }
            return jobDetailList;
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new UnknownException(e.getMessage());
        }
    }

    /**
     * 获取所有的调度器信息
     *
     * @return Cron Trigger 信息列表
     */
    @Override
    public List<QuartzCronTriggerResponse> getAllTriggers() {
        try {
            List<QuartzCronTriggerResponse> triggerList = new ArrayList<>();
            Set<TriggerKey> triggerKeys = scheduler.getTriggerKeys(GroupMatcher.anyGroup());

            for (TriggerKey triggerKey : triggerKeys) {
                Trigger trigger = scheduler.getTrigger(triggerKey);
                QuartzCronTriggerResponse cronTrigger = new QuartzCronTriggerResponse();
                cronTrigger.setName(trigger.getKey().getName());
                cronTrigger.setGroup(trigger.getKey().getGroup());
                cronTrigger.setDescription(trigger.getDescription());
                if (trigger instanceof CronTrigger) {
                    String cronExpression = ((CronTrigger) trigger).getCronExpression();
                    cronTrigger.setCronExpression(cronExpression);
                }
                Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
                cronTrigger.setState(triggerState.name());

                Instant instant = trigger.getNextFireTime().toInstant();
                cronTrigger.setNextFireTime(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()));

                triggerList.add(cronTrigger);
            }
            return triggerList;

        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new UnknownException(e.getMessage());
        }
    }

    /**
     * 暂停一个任务
     *
     * @param jobName  任务名称
     * @param jobGroup 任务分组
     */
    @Override
    public void pauseJob(String jobName, String jobGroup) {
        // TODO 未实现，暂停一个任务就是暂停所有绑定次任务的调度器
    }

    /**
     * 恢复一个任务
     *
     * @param jobName  任务名称
     * @param jobGroup 任务分组
     */
    @Override
    public void resumeJob(String jobName, String jobGroup) {
        // TODO 未实现,恢复一个任务就是恢复所有绑定次任务的调度器
    }


    /**
     * 暂停一个调度器
     *
     * @param triggerName  调度器名称
     * @param triggerGroup 调度器分组名称
     */
    @Override
    public void pauseTrigger(String triggerName, String triggerGroup) {
        try {
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
            scheduler.pauseTrigger(triggerKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new UnknownException(e.getMessage());
        }
    }

    /**
     * 恢复一个调度器
     *
     * @param triggerName  调度器名称
     * @param triggerGroup 调度器分组名称
     */
    @Override
    public void resumeTrigger(String triggerName, String triggerGroup) {
        try {
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
            scheduler.resumeTrigger(triggerKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new UnknownException(e.getMessage());
        }
    }


    /**
     * 动态修改 CronTrigger 的 cronExpression
     *
     * @param triggerName       Trigger 名称
     * @param triggerGroup      Trigger 组名称
     * @param newCronExpression 新的 cron 表达式
     */
    @Override
    public void updateCronTrigger(String triggerName, String triggerGroup, String newCronExpression) {
        try {
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);

            // 获取当前的 Trigger
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                throw new SchedulerException("Trigger not found with key: " + triggerKey);
            }

            // 使用新的 cron 表达式构建新的 CronTrigger
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(newCronExpression);
            CronTrigger newTrigger = trigger.getTriggerBuilder()
                    .withIdentity(triggerKey)
                    .withSchedule(cronScheduleBuilder)
                    .build();

            // 更新调度器中的 Trigger
            scheduler.rescheduleJob(triggerKey, newTrigger);

        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new UnknownException(e.getMessage());
        }
    }


    /**
     * 创建一个新的触发器并将其添加到Quartz调度器中。
     *
     * @param request 包含触发器创建所需信息的TriggerCreateRequest对象
     */
    @Override
    public void createCronTrigger(CronTriggerCreateRequest request) {
        try {
            // 验证 Cron 表达式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(request.getCronExpression());

            // 创建 Trigger
            Trigger newTrigger = TriggerBuilder.newTrigger()
                    .withIdentity(request.getTriggerName(), request.getTriggerGroup())
                    .withSchedule(scheduleBuilder)
                    .withDescription(request.getDescription())
                    .forJob(JobKey.jobKey(request.getJobName(), request.getJobGroup()))
                    .build();

            // 将 Trigger 添加到调度器
            scheduler.scheduleJob(newTrigger);

        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new UnknownException(e.getMessage());
        }
    }


    /**
     * 删除一个任务调度器
     *
     * @param triggerName  任务调度器名称
     * @param triggerGroup 任务调度器分组
     */
    @Override
    public void deleteTrigger(String triggerName, String triggerGroup) {
        try {
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
            // 删除 Trigger
            scheduler.unscheduleJob(triggerKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
            throw new UnknownException(e.getMessage());
        }
    }
}
